﻿using System.Collections;

namespace LxBasic
{
    public class IdLink
    {
        public struct List : ICollection<int>
        {
            public List(Elements elements)
            {
                this.elements = elements.Nodes;
            }
            private Element[] elements;

            private int _Count = 0;
            public int Count => _Count;

            private int _First = -1;
            public int First => _First;

            private int _Last = -1;
            public int Last => _Last;

            public bool IsReadOnly => false;

            public void Add(int item)
            {
                ref var n = ref elements[item];
                if (n.Next != -2)
                {
                    throw new Exception("Error:IdLinkList-Add");
                }
                else
                {
                    n.Next = -1;
                }
                if (_Count == 0)
                {
                    _First = item;
                }
                else
                {
                    elements[_Last].Next = item;
                }
                _Last = item;
                _Count++;
            }

            public void Clear()
            {
                int nid = _First;
                for (int i1 = 0; i1 < _Count; i1++)
                {
                    ref var n = ref elements[nid];
                    nid = n.Next;
                    n.Next = -2;
                }
                _Count = 0;
            }

            public bool Contains(int item)
            {
                foreach (var i in this)
                {
                    if (i == item) return true;
                }
                return false;
            }

            public void CopyTo(int[] array, int arrayIndex)
            {
                foreach (var i in this)
                {
                    array[arrayIndex] = i;
                    arrayIndex++;
                }
            }
            public void CopyTo(List<int> list)
            {
                list.Clear();
                foreach (var i in this)
                {
                    list.Add(i);
                }
            }
            public bool Remove(int item)
            {
                if (_First == item)
                {
                    ref var n = ref elements[item];
                    _First = n.Next;
                    n.Next = -2;
                    _Count--;
                    return true;
                }
                else
                {
                    int nid = _First;
                    for (int i1 = 2; i1 < _Count; i1++)
                    {
                        ref var n = ref elements[nid];
                        if (n.Next == item)
                        {
                            n.Next = elements[item].Next;
                            elements[item].Next = -2;
                            _Count--;
                            return true;
                        }
                        nid = n.Next;
                    }
                    {
                        //如果移除的是最后一个
                        ref var n = ref elements[nid];
                        if (n.Next == item)
                        {
                            _Last = nid;
                            elements[item].Next = -2;
                            _Count--;
                            return true;
                        }
                    }

                }
                return false;
            }

            public IEnumerator<int> GetEnumerator()
            {
                if (_Count > 0)
                {
                    int nid = _First;
                    yield return nid;
                    for (int i1 = 1; i1 < _Count; i1++)
                    {
                        yield return nid = elements[nid].Next;
                    }
                }
            }
            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }

        public class Elements
        {
            public Elements() { }
            public Elements(int idCount)
            {
                Initialize(idCount);
            }
            private Element[] _Nodes;
            public Element[] Nodes => _Nodes;
            public int Count() => _Nodes.Length;

            public void Initialize(int idCount)
            {
                CheckCreator.ArrayStrict(ref _Nodes, idCount);
                Array.Fill(_Nodes, new Element());
            }
            public List CreateList()
            {
                return new List(this);
            }
        }
        public struct Element
        {
            public Element() { }
            public int Next = -2;//>-2为已使用，-1为已使用但是是队尾
        }
        public class IdLinkListTest
        {
            public void Test()
            {
                Test1();
                Test2();
                Test3();
            }
            private void WriteList(List l)
            {
                Console.Write($"Count:{l.Count};Elements:");
                foreach (var i in l)
                {
                    Console.Write(i); Console.Write(",");
                }
                Console.WriteLine();
            }
            public void Test1()
            {
                Console.WriteLine("=====");
                Elements g = new (10);
                List l = new(g);
                l.Add(3);
                l.Add(5);
                WriteList(l);
                Console.WriteLine(l.Contains(3));
                Console.WriteLine("---");
                l.Clear();
                WriteList(l);
                Console.WriteLine(l.Contains(3));
            }
            public void Test2()
            {
                Console.WriteLine("=====");
                Elements g = new(10);
                List l = new(g);
                l.Add(2);
                l.Add(4);
                l.Add(9);
                Console.WriteLine(l.Remove(3));
                Console.WriteLine(l.Contains(4));
                Console.WriteLine(l.Remove(4));
                Console.WriteLine(l.Contains(4));
                l.Add(3);
                WriteList(l);
                Console.WriteLine("---");
                int[] a = new int[20];
                l.CopyTo(a, 3);
                foreach (var ai in a)
                {
                    Console.Write(ai); Console.Write(",");
                }
                Console.WriteLine("---");
            }
            public void Test3()
            {
                Console.WriteLine("=====");
                Elements g = new(10);
                List l = new(g);
                l.Add(2);
                try
                {
                    l.Add(2);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

                l.Add(3);
                l.Add(4);
                l.Add(5);
                l.Add(6);
                l.Add(7);
                l.Add(8);
                WriteList(l);
                Console.WriteLine(l.Remove(2));
                Console.WriteLine(l.Remove(4));
                Console.WriteLine(l.Remove(8));
                WriteList(l);
                l.Add(8);
                WriteList(l);
            }
        }
    }

}
